package practise.leetcode.q37;

import java.util.ArrayList;
import java.util.List;

public class Solution {
    public static final char BLANK = '.';

    private char[][] board;

    public void solveSudoku(char[][] board) {
        this.board = board;
    }

    boolean couldPlace(char num, int row, int col, char[][] board) {
        if (BLANK == num) {
            return false;
        }

        List<Character> chars = availableChars(row, col, board);
        return chars.contains(Character.valueOf(num));
    }

    List<Character> availableChars(int row, int col, char[][] board) {
        List<Character> chars = getAllCharacters();
        chars = rowAvailableChars(row, board, chars);
        chars = colAvailableChars(col, board, chars);
        return boxAvailableChars(row, col, board, chars);
    }

    List<Character> rowAvailableChars(int row, char[][] board, List<Character> chars) {
        char[] oneRow = board[row];
        for (int i = 0; i < oneRow.length; i++) {
            if (oneRow[i] != BLANK) {
                chars.remove(Character.valueOf(oneRow[i]));
            }
        }
        return chars;
    }

    List<Character> colAvailableChars(int col, char[][] board, List<Character> chars) {
        for (int rowIndex = 0; rowIndex < board.length; rowIndex++) {
            if (board[rowIndex][col] != BLANK) {
                chars.remove(Character.valueOf(board[rowIndex][col]));
            }
        }
        return chars;
    }

    List<Character> boxAvailableChars(int row, int col, char[][] board, List<Character> chars) {
        int startRow = row / 3;
        int startCol = col / 3;

        int endRow = startRow + 2;
        int endCol = startCol + 2;

        for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) {
            for (int colIndex = 0; colIndex <= endCol; colIndex++) {
                if (board[rowIndex][colIndex] != BLANK) {
                    chars.remove(Character.valueOf(board[rowIndex][colIndex]));
                }
            }
        }

        return chars;
    }

     List<Character> getAllCharacters() {
        List<Character> results = new ArrayList<>(9);
        char c = '1';
        while (c <= '9') {
            results.add(c++);
        }
        return results;
    }

    private static class State {
        private int row;
        private int col;
        private List<Character> chars;
        private int index;

        State(int row, int col, List<Character> chars, int index) {
            this.row = row;
            this.col = col;
            this.chars = chars;
            this.index = index;
        }

        char next() {
            if (available()) {
                return chars.get(++index).charValue();
            }
            return BLANK;
        }

        boolean available() {
            return chars != null && !chars.isEmpty() && index < chars.size();
        }
    }
}
